/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package principal;

import java.util.ArrayList;

/**
 *
 * @author Pablo
 */
public class IA {
    
    private int profundidadMax;
    private ConstelacionesLogica cl;
    public ConstelacionesEstado estadoJuego;
    
    public IA(int profundidadMax){
        this.profundidadMax=profundidadMax;
        cl=new ConstelacionesLogica();
        estadoJuego = new ConstelacionesEstado();
    }
    
    public int funcionEvaluacion(ConstelacionesEstado ce){
        boolean recorridaBlanca;
        boolean recorridaOscura;
        int tam=cl.contar(ce.segmentos);
        
        if(tam>1){            
            int valor=0; 
            int cAux;
            cAux=cl.contar(ce.segmentos)%2==0?2:1;
            for(Nodo n: ce.nodos){
                if (n.perteneceAConstelacion) continue;
                recorridaBlanca=false;
                recorridaOscura=false;
                if(cl.distancia(n.x, n.y, ce.segmentos[0].x1, ce.segmentos[0].y1)<=75){
                    valor+=4;
                    recorridaBlanca=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[1].x1, ce.segmentos[1].y1)<=75){
                    valor-=4;
                    recorridaOscura=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[tam-cAux].x1, ce.segmentos[tam-cAux].y1)<=75){
                    valor+=4;
                    recorridaBlanca=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[tam-(3-cAux)].x1, ce.segmentos[tam-(3-cAux)].y1)<=75){
                    valor-=4;
                    recorridaOscura=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[0].x1, ce.segmentos[0].y1)>75 && cl.distancia(n.x, n.y, ce.segmentos[0].x1, ce.segmentos[0].y1)<=150
                   &&!recorridaBlanca){
                    valor+=2;
                    recorridaBlanca=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[1].x1, ce.segmentos[1].y1)>75 && cl.distancia(n.x, n.y, ce.segmentos[1].x1, ce.segmentos[1].y1)<=150
                    &&!recorridaOscura){
                    valor-=2;
                    recorridaOscura=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[tam-cAux].x1, ce.segmentos[tam-cAux].y1)>75 && cl.distancia(n.x, n.y, ce.segmentos[tam-cAux].x1, ce.segmentos[tam-cAux].y1)<=150
                   &&!recorridaBlanca){
                    valor+=2;
                    recorridaBlanca=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[tam-(3-cAux)].x1, ce.segmentos[tam-(3-cAux)].y1)>75 && cl.distancia(n.x, n.y, ce.segmentos[tam-(3-cAux)].x1, ce.segmentos[tam-(3-cAux)].y1)<=150
                    &&!recorridaOscura){
                    valor-=2;
                    recorridaOscura=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[0].x1, ce.segmentos[0].y1)>150&&!recorridaBlanca){
                    valor+=1;
                    recorridaBlanca=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[1].x1, ce.segmentos[1].y1)>150&&!recorridaOscura){
                    valor-=1;
                    recorridaOscura=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[tam-cAux].x1, ce.segmentos[tam-cAux].y1)>150&&!recorridaBlanca){
                    valor+=1;
                    recorridaBlanca=true;
                }
                if(cl.distancia(n.x, n.y, ce.segmentos[tam-(3-cAux)].x1, ce.segmentos[tam-(3-cAux)].y1)>150&&!recorridaOscura){
                    valor-=1;
                    recorridaOscura=true;
                }
                
                
                
            }            
            return valor;            
        }
        if(tam==1){
            int valor = 0;
            return valor;
        }
        return 0;
    }
    
    public Integer [] miniMax(ConstelacionesEstado estado,int profundidad){
        //System.out.println("minimax " + profundidad);
        if(estado==null) System.out.println("Estamos en problemas");
        Integer [] resultado = new Integer[3];
            if(profundidad==profundidadMax){
                resultado[0]=estado.jugada[0];
                resultado[1]=estado.jugada[1];
                resultado[2]=funcionEvaluacion(estado);                
                return resultado;
            }            
            int ganador=cl.finJuego();
            if(ganador!=-1){
                resultado[0]=estado.jugada[0];
                resultado[1]=estado.jugada[1];
                resultado[2]=ganador==0?999:-999;
                return resultado;
            }
            ArrayList<ConstelacionesEstado> estados = generarJugadas(estado);
            ArrayList<Integer []> resMinMax = new ArrayList<>();
            for(ConstelacionesEstado e: estados){
                resMinMax.add(miniMax(e,profundidad+1));
            }
            if(estado.turno==ConstelacionesLogica.BLANCA){
                int max=-999;
                /*for(Integer [] r : resMinMax){
                    if(r[2]>max){
                        max=r[2]; resultado=r;
                    }
                }*/
                for(int i=0; i<resMinMax.size(); i++){
                    if(resMinMax.get(i)[2]>max){
                        max=resMinMax.get(i)[2]; 
                        estadoJuego=estados.get(i);
                        resultado=resMinMax.get(i);
                    }
                }
                
            }
            else{
                int min=999;
                /*for(Integer [] r : resMinMax){
                    if(r[2]<min){
                        min=r[2]; resultado=r;
                    }
                }*/
                for(int i=0; i<resMinMax.size(); i++){
                    if(resMinMax.get(i)[2]<min){
                        min=resMinMax.get(i)[2]; 
                        estadoJuego=estados.get(i);
                        resultado=resMinMax.get(i);
                    }
                }
            }
        return resultado;
    }
    public ArrayList<ConstelacionesEstado> generarJugadas(ConstelacionesEstado estado){
        System.out.println("Generando jugadas...");
        int distancia;
        ArrayList<ConstelacionesEstado> resultado= new ArrayList<>();
        //if(estado==null) return resultado;
        if(cl.contar(estado.segmentos)<2){
            for(int i=0; i<estado.nodos.size()-1; i++){
                if(estado.nodos.get(i).perteneceAConstelacion) continue;
                for(int j=i+1; j<estado.nodos.size(); j++){
                    if(estado.nodos.get(j).perteneceAConstelacion) continue;
                    distancia=(int)cl.distancia(estado.nodos.get(i).x, estado.nodos.get(i).y, estado.nodos.get(j).x, estado.nodos.get(j).y);
                    if(distancia>0 && distancia<=75){
                        ConstelacionesEstado nuevo = new ConstelacionesEstado(estado.nodos,estado.segmentos, estado.turno, estado.objetivoB, estado.objetivoO, estado.puntoCercanoObjB, estado.puntoCercanoObjO);
                        nuevo.jugada=estado.jugada;
                        cl.estado=nuevo;                        
                        ArrayList<Integer>  estTemp = new ArrayList<>();
                        estTemp.add(cl.estado.nodos.get(i).x);
                        estTemp.add(cl.estado.nodos.get(i).y);
                        estTemp.add(cl.estado.nodos.get(j).x);
                        estTemp.add(cl.estado.nodos.get(j).y);
                        cl.insertarArista(cl.estado.nodos.get(i).x, cl.estado.nodos.get(i).y, cl.estado.nodos.get(j).x, cl.estado.nodos.get(j).y, cl.estado.turno, 0, estTemp);
                        cl.estado.turno=cl.estado.turno==ConstelacionesLogica.BLANCA?ConstelacionesLogica.OSCURA:ConstelacionesLogica.BLANCA;
                        resultado.add(nuevo);                    
                       
                    }
                }
            }
        }
        else{
            for(int i=0; i<estado.nodos.size(); i++){
                if(estado.nodos.get(i).perteneceAConstelacion) continue;
                distancia=(int)cl.distancia(estado.segmentos[cl.estado.turno].x1, estado.segmentos[cl.estado.turno].y1, estado.nodos.get(i).x, estado.nodos.get(i).y);
                if(distancia>0 && distancia<=75){
                    ConstelacionesEstado nuevo = new ConstelacionesEstado(estado.nodos,estado.segmentos, estado.turno, estado.objetivoB, estado.objetivoO, estado.puntoCercanoObjB, estado.puntoCercanoObjO);
                    nuevo.jugada=estado.jugada;
                    cl.estado=nuevo;
                    ArrayList<Integer>  estTemp = new ArrayList<>();
                    estTemp.add(cl.estado.nodos.get(i).x);
                    estTemp.add(cl.estado.nodos.get(i).y);
                    int pfx=estado.segmentos[cl.estado.turno].x1+(int)(75*((cl.estado.nodos.get(i).x-estado.segmentos[cl.estado.turno].x1)/cl.distancia(estado.segmentos[cl.estado.turno].x1, estado.segmentos[cl.estado.turno].y1, estado.nodos.get(i).x, estado.nodos.get(i).y)));
                    int pfy=estado.segmentos[cl.estado.turno].y1+(int)(75*((cl.estado.nodos.get(i).y-estado.segmentos[cl.estado.turno].y1)/cl.distancia(estado.segmentos[cl.estado.turno].x1, estado.segmentos[cl.estado.turno].y1, estado.nodos.get(i).x, estado.nodos.get(i).y)));
                    cl.insertarArista(pfx,pfy,estado.segmentos[cl.estado.turno].x1,estado.segmentos[cl.estado.turno].y1,cl.estado.turno, 0, estTemp);
                    cl.estado.turno=cl.estado.turno==ConstelacionesLogica.BLANCA?ConstelacionesLogica.OSCURA:ConstelacionesLogica.BLANCA;
                    resultado.add(nuevo);
                }
                if(cl.contar(estado.segmentos)<10) {
                    distancia=(int)cl.distancia(estado.segmentos[cl.contar(cl.estado.segmentos)-2].x2, estado.segmentos[cl.contar(cl.estado.segmentos)-2].y2, estado.nodos.get(i).x, estado.nodos.get(i).y);
                    if(distancia>0 && distancia<=75){
                        ConstelacionesEstado nuevo = new ConstelacionesEstado(estado.nodos,estado.segmentos, estado.turno, estado.objetivoB, estado.objetivoO, estado.puntoCercanoObjB, estado.puntoCercanoObjO);
                        nuevo.jugada=estado.jugada;
                        cl.estado=nuevo;
                        ArrayList<Integer>  estTemp = new ArrayList<>();
                        estTemp.add(cl.estado.nodos.get(i).x);
                        estTemp.add(cl.estado.nodos.get(i).y);
                        cl.insertarArista(estado.segmentos[cl.contar(cl.estado.segmentos)-2].x2, estado.segmentos[cl.contar(cl.estado.segmentos)-2].y2, estado.nodos.get(i).x, estado.nodos.get(i).y,cl.estado.turno, 1, estTemp);
                        cl.estado.turno=cl.estado.turno==ConstelacionesLogica.BLANCA?ConstelacionesLogica.OSCURA:ConstelacionesLogica.BLANCA;
                        resultado.add(nuevo);
                    }                    
                }
                else{                    
                    if(cl.distancia(estado.segmentos[cl.contar(cl.estado.segmentos)-2+cl.estado.turno].x1, estado.segmentos[cl.contar(cl.estado.segmentos)-2+cl.estado.turno].y1, estado.nodos.get(i).x, estado.nodos.get(i).y)<=75){
                        ConstelacionesEstado nuevo = new ConstelacionesEstado(estado.nodos,estado.segmentos, estado.turno, estado.objetivoB, estado.objetivoO, estado.puntoCercanoObjB, estado.puntoCercanoObjO);
                        nuevo.jugada=estado.jugada;
                        cl.estado=nuevo;
                        ArrayList<Integer>  estTemp = new ArrayList<>();
                        estTemp.add(cl.estado.nodos.get(i).x);
                        estTemp.add(cl.estado.nodos.get(i).y);
                        cl.insertarArista(estado.segmentos[cl.contar(cl.estado.segmentos)-2+cl.estado.turno].x1, estado.segmentos[cl.contar(cl.estado.segmentos)-2+cl.estado.turno].y1, estado.nodos.get(i).x, estado.nodos.get(i).y,cl.estado.turno, 1, estTemp);
                        cl.estado.turno=cl.estado.turno==ConstelacionesLogica.BLANCA?ConstelacionesLogica.OSCURA:ConstelacionesLogica.BLANCA;
                        resultado.add(nuevo);
                    }                  
               }
            }
        }
        return resultado;
    }
    
    public void primeroMejor(ConstelacionesEstado estado){
        Integer [] resultado = new Integer[3];
        ArrayList<ConstelacionesEstado> estados;
        estados=generarJugadas(estado);
        int max=-999;
        int min=999;
        if(cl.estado.turno==ConstelacionesLogica.BLANCA){
            for(ConstelacionesEstado ce: estados){
                int fe=funcionEvaluacion(ce);
                if(fe>max){
                    max=fe;
                    estadoJuego=ce;
                }
            }
        }
        else{
            for(ConstelacionesEstado ce: estados){
                int fe=funcionEvaluacion(ce);
                if(fe<min){
                    min=fe;                    
                    estadoJuego=ce;
                }
            }
        }  
        
    }
}
